#ifndef XGE_XLOOP_SYNC_H_
#define XGE_XLOOP_SYNC_H_
#include "xge_common_config.h"
#include "xassert.h"
#include "xthread_debug.h"
#include "xtimer.h"
#include "xdata_structure.h"

namespace xge{
namespace xge_internal{
  // LoopSync class provide interface for those class want to receive
  // loop sync message class a common base .
  // Loop Sync class means the LoopTicking virtual function will be called
  // inside of the MainLoop , and it will receive the time message of the
  // difference between two loop . It is not a game entity interface , it
  // is specifically for the infrastructure layer .

  // The derive class SHOULD ONLY be created in the main thread . 
  // Since derive this class will make your derive class not thread safe ( Only creation )
  class LoopSync{
  public:
    // It will receive the tick_t class as the time_stuff 
    // and when receive this message , the derive class will
    // do some audition stuff or other things .
    virtual void LoopTicking( const Timer::tick_t& diff_time ) =0;
    // Update the whole loop sync list object
    // this function will be called by the system loop ( Main Thread Loop )
    static void UpdateLoopSync( const Timer::tick_t& time_diff );

  public:
    // LoopSync CTor
    // this function basically register this pointer to the map 
    // and ASSERT that this class should be lay in the main thread instead of other thread
    inline LoopSync();
    // LoopSync Dtor
    // this function basically unregister this pointer from the map 
    inline virtual ~LoopSync();
  private:
    // Using address key as our map key ( this is the class address value )
    typedef unsigned int AddressKey ;
    // A map for storing the loop sync stuff 
    typedef xge::map< AddressKey , LoopSync* >::Map LoopSyncMap;
    // get the loop sync map 
    // this is not thread safe ( You should only bound this calling in the Main Thread )
    inline static LoopSyncMap& GetLoopSyncMap() ;
    // the internal register function 
    // using a wrapper function in order to meet the future stuff
    inline static void RegisterXLoopSyncObject( LoopSync* this_pointer );
    // the internal unregister function
    // using a wrapper function in order to meet the future stuff
    inline static void UnregisterXLoopSyncObject( LoopSync* this_pointer );

  };

  LoopSync::LoopSyncMap& LoopSync::GetLoopSyncMap() {
    // This function is not thread safe 
    // since we should always make XLoopSync object in main thread 
    // so we don't need thread safe initialization for kMap
    static LoopSyncMap kMap;
    return kMap;
  }

  void LoopSync::RegisterXLoopSyncObject( LoopSync* this_pointer ) {
    std::pair< LoopSyncMap::iterator, bool > ret =
      GetLoopSyncMap().insert( LoopSyncMap::value_type( (AddressKey)(this_pointer) , this_pointer ) );
    XASSERT(ret.second);
  }

  void LoopSync::UnregisterXLoopSyncObject( LoopSync* this_pointer ) {
    LoopSyncMap::iterator ifind = GetLoopSyncMap().find((AddressKey)(this_pointer));
    XASSERT(ifind != GetLoopSyncMap().end() );
    GetLoopSyncMap().erase(ifind);
  }

  LoopSync::LoopSync() {
    // Assert this class is in the main thread
    XASSERT_SLOW(ThreadDebug::IsInMainThread());
    RegisterXLoopSyncObject(this);
  }

  inline LoopSync::~LoopSync() {
    // Assert this class is in the main thread
    XASSERT_SLOW(ThreadDebug::IsInMainThread());
    UnregisterXLoopSyncObject(this);
  }

}// namespace xge_internal
}// namespace xge

#endif// XGE_XTICKABLE_H_